home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2002 #3 / Amiga Plus CD - 2002 - No. 03.iso / AmigaPlus / Tools / Development / renderlib40 / src / rnd_scale.c < prev    next >
Encoding:
C/C++ Source or Header  |  2003-01-04  |  9.4 KB  |  488 lines

  1.  
  2. #include "lib_init.h"
  3. #include "lib_debug.h"
  4. #include <render/render.h>
  5. #include <render/renderhooks.h>
  6. #include <utility/hooks.h>
  7. #include <proto/utility.h>
  8. #include <proto/exec.h>
  9.  
  10.  
  11. struct TxLine
  12. {
  13.     WORD w;
  14.     WORD x0;
  15.     LONG stx, sty, dtx, dty;
  16. };
  17.  
  18.  
  19. #define NUMV        4
  20.  
  21. static void inittexture(WORD *coords, WORD *texcoords, LONG width, LONG height, struct TxLine *txline)
  22. {
  23.     LONG upperindex, index, lowery, uppery, j, k;
  24.     LONG bordertableft[8], bordertabright[8];
  25.     LONG *bpl, *bpr;
  26.     LONG y, indexleft, indexright, ycountleft, ycountright;
  27.     FLOAT stxl, styl, aktleftx, stxr, styr, aktrightx, f;
  28.     FLOAT dtxl, dtyl, deltaxleft, dtxr, dtyr, deltaxright;
  29.  
  30.     LONG turnindex = 
  31.         ((coords[2]-coords[0]) * (coords[5]-coords[1]) -
  32.         (coords[4]-coords[0]) * (coords[3]-coords[1])) > 0 ? 1 : -1;
  33.  
  34.  
  35.     upperindex = 0;
  36.     index = 0;
  37.     lowery = uppery = (LONG) coords[(index<<1)+1];
  38.     j = 1;
  39.  
  40.     do
  41.     {
  42.         index = j;
  43.         y = (LONG) coords[(index<<1)+1];
  44.         if (y < uppery)
  45.         {
  46.             upperindex = j;
  47.             uppery = y;
  48.         }
  49.         if (y > lowery)
  50.         {
  51.             lowery = y;
  52.         }
  53.     } while (++j < NUMV);
  54.         
  55.         
  56.     if (uppery >= lowery) return;
  57.     
  58.      bpl = bordertableft;
  59.      k = 2;
  60.  
  61.     for(;;)
  62.     {
  63.         index = upperindex;
  64.  
  65.         for(;;)
  66.         {        
  67.             j = index - turnindex;
  68.             if (j == NUMV)
  69.             {
  70.                 j = 0;
  71.             }
  72.             else if (j < 0)
  73.             {
  74.                 j = NUMV - 1;
  75.             }
  76.     
  77.             if ((LONG) coords[(j<<1)+1] != uppery)
  78.             {
  79.                 break;
  80.             }
  81.  
  82.             index = j;
  83.         }
  84.         
  85.         while ((LONG) coords[(index<<1)+1] < lowery)
  86.         {
  87.             *bpl++ = index << 1;
  88.             index -= turnindex;
  89.             if (index == NUMV)
  90.             {
  91.                 index = 0;
  92.             }
  93.             else if (index < 0)
  94.             {
  95.                 index = NUMV-1;
  96.             }
  97.         }
  98.         
  99.         *bpl = index << 1;
  100.         
  101.         if (--k == 0) break;
  102.         
  103.         bpl = bordertabright;
  104.         turnindex = -turnindex;
  105.     }
  106.  
  107.     
  108.     txline += uppery;
  109.  
  110.     
  111.     bpl = bordertableft;
  112.     bpr = bordertabright;
  113.     
  114.     indexleft = *bpl;
  115.     indexright = *bpr;
  116.  
  117.     ycountleft = 0;
  118.     ycountright = 0;    
  119.  
  120.     y = uppery;
  121.  
  122.  
  123.     do
  124.     {
  125.         if (ycountleft == 0)
  126.         {
  127.             stxl = texcoords[indexleft];
  128.             styl = texcoords[indexleft+1];
  129.             aktleftx = coords[indexleft];
  130.             ycountleft = - (LONG) coords[indexleft+1];
  131.             indexleft = *(++bpl);
  132.             ycountleft += (LONG) coords[indexleft+1];
  133.             f = 1 / (FLOAT) ycountleft;
  134.             dtxl = (texcoords[indexleft]-stxl)*f;
  135.             dtyl = (texcoords[indexleft+1]-styl)*f;
  136.             deltaxleft = (coords[indexleft]-aktleftx)*f;
  137.         }
  138.  
  139.         if (ycountright == 0)
  140.         {
  141.             stxr = texcoords[indexright];
  142.             styr = texcoords[indexright+1];
  143.             aktrightx = coords[indexright];
  144.             ycountright = - (LONG) coords[indexright+1];
  145.             indexright = *(++bpr);
  146.             ycountright += (LONG) coords[indexright+1];
  147.             f = 1 / (FLOAT) ycountright;
  148.             dtxr = (texcoords[indexright]-stxr)*f;
  149.             dtyr = (texcoords[indexright+1]-styr)*f;
  150.             deltaxright = (coords[indexright]-aktrightx)*f;
  151.         }
  152.  
  153.  
  154.         if (y >= 0)
  155.         {
  156.             LONG x0, x1, w;
  157.  
  158.             if (y >= height) return;
  159.  
  160.             x0 = (LONG) aktleftx;
  161.             x1 = (LONG) aktrightx;
  162.             w = x1 - x0;
  163.             
  164.             if (w > 0)
  165.             {
  166.                 LONG stx,sty;
  167.                 LONG dtx,dty;
  168.  
  169.                 stx = stxl * 65536;
  170.                 sty = styl * 65536;
  171.                 f = 65536 / (FLOAT) w;
  172.                 dtx = (LONG) ((stxr-stxl)*f);
  173.                 dty = (LONG) ((styr-styl)*f);
  174.                 
  175.                 if (x0 < 0)
  176.                 {
  177.                     stx -= x0*dtx;
  178.                     sty -= x0*dty;
  179.                     w += x0;
  180.                     x0 = 0;
  181.                 }
  182.                 if (x1 >= width)
  183.                 {
  184.                     w -= x1-width+1;
  185.                 }
  186.  
  187.                 if (w > 0)
  188.                 {
  189.                     txline->w = w;
  190.                     txline->x0 = x0;
  191.                     txline->stx = stx;
  192.                     txline->sty = sty;
  193.                     txline->dtx = dtx;
  194.                     txline->dty = dty;
  195.                 }
  196.             }
  197.         }
  198.  
  199.         aktleftx += deltaxleft;
  200.         aktrightx += deltaxright;
  201.         stxl += dtxl;
  202.         styl += dtyl;
  203.         stxr += dtxr;
  204.         styr += dtyr;
  205.         
  206.         ycountleft--;
  207.         ycountright--;
  208.         txline++;
  209.  
  210.     } while (++y < lowery);
  211. }
  212.  
  213.  
  214. static void scale_text_clut(RNDSCALE *sce, struct ScaleData *data, UBYTE *src, UBYTE *dst, LONG dy, WORD tsw)
  215. {
  216.     struct TxLine *txline = ((struct TxLine *) data->data) + dy;
  217.     LONG stx = txline->stx;
  218.     LONG sty = txline->sty;
  219.     LONG dtx = txline->dtx;
  220.     LONG dty = txline->dty;
  221.     WORD w = txline->w;
  222.  
  223.     dst += txline->x0;
  224.     
  225.     while (w--)
  226.     {
  227.         *dst++ = src[(stx >> 16) + (sty >> 16) * tsw];
  228.         stx += dtx;
  229.         sty += dty;
  230.     }        
  231. }
  232.  
  233. static void scale_text_rgb(RNDSCALE *sce, struct ScaleData *data, ULONG *src, ULONG *dst, LONG dy, WORD tsw)
  234. {
  235.     struct TxLine *txline = ((struct TxLine *) data->data) + dy;
  236.     LONG stx = txline->stx;
  237.     LONG sty = txline->sty;
  238.     LONG dtx = txline->dtx;
  239.     LONG dty = txline->dty;
  240.     WORD w = txline->w;
  241.  
  242.     dst += txline->x0;
  243.     
  244.     while (w--)
  245.     {
  246.         *dst++ = src[(stx >> 16) + (sty >> 16) * tsw];
  247.         stx += dtx;
  248.         sty += dty;
  249.     }        
  250. }
  251.  
  252.  
  253.  
  254.  
  255.  
  256. static BOOL scale_init(RNDSCALE *sce, struct ScaleData *data)
  257. {
  258.     if (sce->usecoords)
  259.     {
  260.         data->data = AllocRenderVecClear(sce->rmh, sizeof(struct TxLine) * sce->dh);
  261.         if (data->data)
  262.         {
  263.             WORD tc[8];
  264.             tc[0] = 0; tc[1] = 0;
  265.             tc[2] = sce->sw-1; tc[3] = 0;
  266.             tc[4] = sce->sw-1; tc[5] = sce->sh-1;
  267.             tc[6] = 0; tc[7] = sce->sh-1;
  268.             inittexture(sce->coords, tc, sce->dw, sce->dh, data->data);
  269.             return TRUE;
  270.         }
  271.         return FALSE;
  272.     }
  273.  
  274.     data->cy = 0;
  275.     data->sourcey = 0;
  276.  
  277.     data->deltax = sce->sw - 1;
  278.     data->deltax /= (sce->dw - 1);
  279.  
  280.     data->deltay = sce->sh - 1;
  281.     data->deltay /= (sce->dh - 1);
  282.  
  283.     return TRUE;
  284. }
  285.  
  286. static void scale_exit(RNDSCALE *sce, struct ScaleData *data)
  287. {
  288.     if (sce->usecoords) FreeRenderVec(data->data);
  289. }
  290.  
  291.  
  292.  
  293.  
  294. static void scale_line_clut(RNDSCALE *sce, struct ScaleData *data, UBYTE *src, UBYTE *dst, LONG dy, WORD tsw)
  295. {
  296.     LONG w8 = (sce->dw >> 3) + 1;
  297.     LONG cx = 0;
  298.     LONG dx = data->deltax * 65536;
  299.     src += data->cy * tsw;
  300.     switch (sce->dw & 7)
  301.     {
  302.         do
  303.         {
  304.                     *dst++ = src[cx>>16]; cx += dx;
  305.             case 7:    *dst++ = src[cx>>16]; cx += dx;
  306.             case 6:    *dst++ = src[cx>>16]; cx += dx;
  307.             case 5:    *dst++ = src[cx>>16]; cx += dx;
  308.             case 4:    *dst++ = src[cx>>16]; cx += dx;
  309.             case 3:    *dst++ = src[cx>>16]; cx += dx;
  310.             case 2:    *dst++ = src[cx>>16]; cx += dx;
  311.             case 1:    *dst++ = src[cx>>16]; cx += dx;
  312.             case 0:    w8--;
  313.  
  314.         } while (w8);
  315.     }    
  316.  
  317.     data->cy = data->sourcey += data->deltay;
  318. }
  319.  
  320. static void scale_line_rgb(RNDSCALE *sce, struct ScaleData *data, ULONG *src, ULONG *dst, LONG dy, WORD tsw)
  321. {
  322.     LONG w8 = (sce->dw >> 3) + 1;
  323.     LONG cx = 0;
  324.     LONG dx = data->deltax * 65536;
  325.     src += data->cy * tsw;
  326.     switch (sce->dw & 7)
  327.     {
  328.         do
  329.         {
  330.                     *dst++ = src[cx>>16]; cx += dx;
  331.             case 7:    *dst++ = src[cx>>16]; cx += dx;
  332.             case 6:    *dst++ = src[cx>>16]; cx += dx;
  333.             case 5:    *dst++ = src[cx>>16]; cx += dx;
  334.             case 4:    *dst++ = src[cx>>16]; cx += dx;
  335.             case 3:    *dst++ = src[cx>>16]; cx += dx;
  336.             case 2:    *dst++ = src[cx>>16]; cx += dx;
  337.             case 1:    *dst++ = src[cx>>16]; cx += dx;
  338.             case 0:    w8--;
  339.  
  340.         } while (w8);
  341.     }    
  342.  
  343.     data->cy = data->sourcey += data->deltay;
  344. }
  345.  
  346. /************************************************************************** 
  347. **
  348. **    createscaleengine
  349. */
  350.  
  351. LIBAPI RNDSCALE *CreateScaleEngineA(UWORD sw, UWORD sh, UWORD dw, UWORD dh, struct TagItem *tags)
  352. {
  353.     RNDMH *rmh = (RNDMH *) GetTagData(RND_RMHandler, NULL, tags);
  354.     UWORD format = GetTagData(RND_PixelFormat, PIXFMT_CHUNKY_CLUT, tags);
  355.     APTR scalefunc;
  356.     UWORD bpp;
  357.     RNDSCALE *sce;
  358.  
  359.     switch (format)
  360.     {
  361.         default: 
  362.             return NULL;
  363.  
  364.         case PIXFMT_CHUNKY_CLUT:
  365.             scalefunc = (APTR) scale_line_clut;
  366.             bpp = 1;
  367.             break;
  368.  
  369.         case PIXFMT_0RGB_32:
  370.             scalefunc = (APTR) scale_line_rgb;
  371.             bpp = 4;
  372.             break;
  373.     }
  374.     
  375.     sce = AllocRenderVec(rmh, sizeof(RNDSCALE));
  376.     if (sce)
  377.     {
  378.         UWORD *coords = (UWORD *) GetTagData(RND_DestCoordinates, NULL, tags);
  379.         if (coords)
  380.         {
  381.             sce->usecoords = TRUE;
  382.             TurboCopyMem(coords, sce->coords, sizeof(WORD) * 8);
  383.             if (format == PIXFMT_CHUNKY_CLUT)
  384.             {
  385.                 scalefunc = (APTR) scale_text_clut;
  386.             }
  387.             else
  388.             {
  389.                 scalefunc = (APTR) scale_text_rgb;
  390.             }
  391.         }
  392.         else
  393.         {
  394.             sce->usecoords = FALSE;
  395.         }
  396.         sce->rmh = rmh;
  397.         sce->sw = sw;
  398.         sce->sh = sh;
  399.         sce->dw = dw;
  400.         sce->dh = dh;
  401.         sce->format = format;
  402.         sce->bpp = bpp;
  403.         sce->scalefunc = (void (*)(RNDSCALE *, struct ScaleData *, APTR, APTR, LONG, WORD)) scalefunc;
  404.         sce->initfunc = scale_init;
  405.         sce->exitfunc = scale_exit;
  406.     }
  407.     return sce;
  408. }
  409.  
  410. /************************************************************************** 
  411. **
  412. **    deletescaleengine
  413. */
  414.  
  415. LIBAPI void DeleteScaleEngine(RNDSCALE *engine)
  416. {
  417.     FreeRenderVec((ULONG *) engine);    
  418. }
  419.  
  420. /************************************************************************** 
  421. **
  422. **    scale
  423. */
  424.  
  425. LIBAPI ULONG ScaleA(RNDSCALE *sce, UBYTE *src, UBYTE *dst, struct TagItem *tags)
  426. {
  427.     ULONG result = CONV_NO_DATA;
  428.     if (sce && src && dst)
  429.     {
  430.         struct ScaleData scdata;
  431.         result = CONV_NOT_ENOUGH_MEMORY;
  432.         if ((*sce->initfunc)(sce, &scdata))
  433.         {
  434.             struct Hook *linehook = (struct Hook *) GetTagData(RND_LineHook, NULL, tags);
  435.             LONG tsw = GetTagData(RND_SourceWidth, sce->sw, tags);
  436.             LONG tdw = GetTagData(RND_DestWidth, sce->dw, tags) * sce->bpp;
  437.             LONG y;
  438.  
  439.             if (linehook)
  440.             {
  441.                 struct RND_LineMessage fetchmsg, rendermsg;
  442.                 fetchmsg.RND_LMsg_type = LMSGTYPE_LINE_FETCH;
  443.                 rendermsg.RND_LMsg_type = LMSGTYPE_LINE_RENDERED;
  444.     
  445.                 result = CONV_CALLBACK_ABORTED;
  446.                 for (y = 0; y < sce->dh; ++y)
  447.                 {
  448.                     fetchmsg.RND_LMsg_row = scdata.sourcey;
  449.                     if (!CallHookPkt(linehook, src + scdata.cy * tsw, &fetchmsg)) goto abort;
  450.                 
  451.                     (*sce->scalefunc)(sce, &scdata, src, dst, y, tsw);
  452.     
  453.                     rendermsg.RND_LMsg_row = y;
  454.                     if (!CallHookPkt(linehook, dst, &rendermsg)) goto abort;
  455.     
  456.                     dst += tdw;
  457.                 }
  458.             }
  459.             else
  460.             {
  461.                 for (y = 0; y < sce->dh; ++y)
  462.                 {
  463.                     (*sce->scalefunc)(sce, &scdata, src, dst, y, tsw);
  464.                     dst += tdw;
  465.                 }
  466.             }
  467.             
  468.             result = CONV_SUCCESS;
  469.  
  470. abort:        (*sce->exitfunc)(sce, &scdata);
  471.         }
  472.     }
  473.     return result;
  474. }
  475.  
  476. /************************************************************************** 
  477. **
  478. **    scaleordinate
  479. */
  480.  
  481. LIBAPI UWORD ScaleOrdinate(UWORD source, UWORD dest, UWORD ordinate)
  482. {
  483.     FLOAT o = (FLOAT) (source - 1) / (dest - 1);
  484.     o *= ordinate;
  485.     return (UWORD) o;
  486. }
  487.  
  488.